package org.fujene.toolbox;

public class ByteConverter{
	// バイト列を整数に変換
	// バイト列をコピーさせなくてすむように big-endian固定
	public static int byteToInt(byte[] b, int from, int length){
		int temp = 0;
		if(length > 4 || length <= 0) length = 4;

		for(int i = from; i < from + length; i++){
			// Big endian
			temp <<= 8;
			temp += (b[i] & 0xff);
		}

		// 補数操作
		if(temp >= 0 && ((temp & (1 << (length * 8 - 1))) != 0)){
			temp -= (1 << (length * 8));
		}

		return temp;
	}

	// バイト列をそのままintにできるように
	public static int byteToInt(byte[] b){
		return byteToInt(b, 0, b.length);
	}

	public static long byteToLong(byte[] b, int from, int length){
		long temp = 0L;
		if(length > 8 || length <= 0) length = 8;

		for(int i = from; i < from + length; i++){
			// Big endian
			temp <<= 8;
			temp += (b[i] & 0xff);
		}

		// 補数操作
		if(temp >= 0 && ((temp & (1L << (length * 8 - 1))) != 0)) temp -= (1L << (length * 8));

		return temp;
	}

	// バイト列->long
	public static long byteToLong(byte[] b){
		return byteToLong(b, 0, b.length);
	}

	// int -> byte[] big-endian
	public static byte[] intToByte(int i, int length){
		assert length < 5;
		byte[] newbyte = new byte[length];

		for(int j = length - 1; j >= 0; j--){
			newbyte[j] = (byte)(i & 0xFF);
			i >>= 8;
		}

		return newbyte;
	}

	// long -> byte[] big-endian
	public static byte[] longToByte(long l, int length){
		assert length < 9;
		long tmp = l;
		byte[] newbyte = new byte[length];

		for(int j = length - 1; j >= 0; j--){
			newbyte[j] = (byte)(tmp & 0xFF);
			tmp >>= 8;
		}

		return newbyte;
	}

	// バイト列 -> int列
	public static int[] byteToIntArray(byte[] b, int from, int intlength){
		assert b.length > intlength * 4;
		int[] result = new int[intlength];
		int pointer = from;

		for(int i = 0; i < result.length; i++, pointer += 4){
			result[i] = byteToInt(b, pointer, 4);
		}

		return result;
	}

	public static long mergeInteger(int upper, int lower){
		long val = (upper << 32) + lower;
		return val;
	}

	public static int[] divideLong(long input){
		int[] vals = new int[]{ ((int)(input & 0xFFFFFFFF00000000L) >> 32), (int)(input & 0xFFFFFFFF) };
		return vals;
	}
}